import { Graph, Shape, Addon, FunctionExt } from '@antv/x6'
import { initRegisterNodes, ModelRect } from './nodes'
import initRegisterEdges from './edges'
import { items } from './items'

/**
 * 初始化图
 * @param {HTMLElement} wrapper 包装器
 * @param {HTMLElement} container 容器，container似乎只是用于撑开包装器，没有用到
 * @param {HTMLElement} minimapContainer minimap容器
 * @returns {Graph} graph 图
 */
 function initGraph(wrapper, container, minimapContainer) {
  const graph = new Graph({
    container: wrapper,
    autoResize: true,
    // 绘制网格
    grid: {
      size: 10,
      visible: true,
      type: 'mesh',
      args: {
        color: '#e0e0e0',
        thickness: 1,
      },
    },
    // 背景
    background: {
      color: '#eeeeee',
      // image: require('../../../assets/logo.svg'),
      image:
        'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',
      position: 'center',
      size: {
        width: 400,
        height: 300,
      },
      repeat: 'repeat',
      opacity: 0.1,
    },
    // 对齐线
    snapline: true,
    // 滚动画布
    scroller: {
      enabled: true,
      pannable: true,
    },
    // 小地图
    minimap: {
      enabled: true,
      container: minimapContainer,
      width: 240,
      height: 160,
    },
    // 撤销、重做
    history: true,
    // 剪切板
    clipboard: true,
    // 键盘快捷键
    keyboard: true,
    // 鼠标滚轮缩放
    mousewheel: {
      enabled: true,
      modifiers: ['ctrl'],
    },
    // 点选、框选
    selecting: {
      enabled: true,
      rubberband: true,
      modifiers: ['alt'],
    },
    // 旋转节点
    rotating: false,
    // 缩放节点
    resizing: false,
    // 平移节点
    translating: {
      restrict: false,
    },
    // 平移缩放节点的基础选项
    transforming: {
      clearAll: true,
      clearOnBlankMouseDown: true,
    },
    // 嵌套节点
    embedding: {
      enabled: true,
      findParent: 'bbox',
      frontOnly: true,
    },
    // 连线选项
    connecting: {
      snap: {
        radius: 50,
      },
      allowBlank: false,
      allowMulti: 'withPort',
      allowLoop: false,
      allowNode: false,
      allowEdge: false,
      allowPort: true,
      highlight: true,
      connector: 'rounded',
      connectionPoint: 'boundary',
      router: {
        name: 'er',
        args: {
          direction: 'V',
        },
      },
      createEdge() {
        return new Shape.Edge({
          attrs: {
            line: {
              stroke: '#a0a0a0',
              strokeWidth: 1,
              targetMarker: {
                name: 'classic',
                size: 7,
              },
            },
          },
        })
      },
      validateConnection({ sourceView, targetView, targetMagnet }) {
        if (!targetMagnet) {
          return false
        }
        if (targetMagnet.getAttribute('port-group') !== 'in') {
          return false
        }
        if (targetView) {
          const node = targetView.ceil
          if (node) {
            const portId = targetMagnet.getAttribute('port')
            const usedInPorts = node.getUsedInPorts(graph)
            if (usedInPorts.find((port) => port && port.id === portId)) {
              return false
            }
          }
        }
        return true
      },
    },
    // 高亮选项
    highlighting: {
      magnetAvailable: {
        name: 'stroke',
        args: {
          padding: 4,
          attrs: {
            'stroke-width': 2,
            stroke: 'red',
          },
        },
      },
      magnetAdsorbed: {
        name: 'stroke',
        args: {
          attrs: {
            fill: '#fff',
            stroke: '#31d0c6',
          },
        },
      },
    },
  })

  window.addEventListener('resize', () => {
    const width = wrapper.clientWidth
    const height = wrapper.clientHeight
    graph.resize(width, height)
    graph.centerContent()
  })

  initEvents(graph)

  return graph
}

/**
 * 初始化Stencil
 * @param {Graph} graph 图实例
 * @param {HTMLElement} container 容器
 * @returns {Stencil} stencil stencil实例
 */
function initStencil(graph, container) {
  const stencil = new Stencil({
    title: 'Components',
    target: graph,
    search(cell, keyword) {
      return cell.shape.indexOf(keyword) !== -1
    },
    placeholder: 'Search ...',
    notFoundText: 'Not Found',
    collapsable: true,
    stencilGraphWidth: 300,
    stencilGraphHeight: 180,
    groups: [
      {
        name: 'basic',
        title: 'Basic Components',
        graphHeight: 500,
        layoutOptions: {
          columns: 1,
          marginX: 60,
        },
      },
      {
        name: 'other',
        title: 'Other Components',
        collapsable: true,
        collapsed: true,
        graphHeight: 500,
        layoutOptions: {
          columns: 1,
          marginX: 60,
        },
      },
    ],
  })

  container.appendChild(stencil.container)

  // 添加图元
  items.forEach((item) => {
    const title = item.title
    const elements = item.elements.map((element) => {
      let portItems = []
      Object.keys(element.ports).forEach((key) => {
        element.ports[key].forEach((aPortOfKey) => {
          if (typeof aPortOfKey === 'string') {
            let portItem = {
              id: aPortOfKey,
              group: key,
              attrs: {
                text: {
                  text: aPortOfKey,
                },
              },
            }
            portItems.push(portItem)
          }
        })
      })

      return new ModelRect({
        label: element.label,
        ports: {
          items: portItems,
        },
      })
    })

    stencil.load(elements, title)
  })

  // const r = new ModelRect({
  //   label: 'Hello',
  //   ports: {
  //     items: [
  //       {
  //         id: 'port1',
  //         group: 'in',
  //         attrs: {
  //           text: {
  //             text: 'port1',
  //           },
  //         },
  //       },
  //     ],
  //   },
  //   width: 70,
  //   height: 40,
  //   attrs: {
  //     rect: { fill: '#31D0C6', stroke: '#4B4A67', strokeWidth: 6 },
  //     text: { text: 'rect', fill: 'white' },
  //   },
  // })

  // const c = new Circle({
  //   width: 60,
  //   height: 60,
  //   attrs: {
  //     circle: { fill: '#FE854F', strokeWidth: 6, stroke: '#4B4A67' },
  //     text: { text: 'ellipse', fill: 'white' },
  //   },
  // })

  // const c2 = new Circle({
  //   width: 60,
  //   height: 60,
  //   attrs: {
  //     circle: { fill: '#4B4A67', 'stroke-width': 6, stroke: '#FE854F' },
  //     text: { text: 'ellipse', fill: 'white' },
  //   },
  // })

  // const r2 = new Rect({
  //   width: 70,
  //   height: 40,
  //   attrs: {
  //     rect: { fill: '#4B4A67', stroke: '#31D0C6', strokeWidth: 6 },
  //     text: { text: 'rect', fill: 'white' },
  //   },
  // })

  // const r3 = new Rect({
  //   width: 70,
  //   height: 40,
  //   attrs: {
  //     rect: { fill: '#31D0C6', stroke: '#4B4A67', strokeWidth: 6 },
  //     text: { text: 'rect', fill: 'white' },
  //   },
  // })

  // const c3 = new Circle({
  //   width: 60,
  //   height: 60,
  //   attrs: {
  //     circle: { fill: '#FE854F', strokeWidth: 6, stroke: '#4B4A67' },
  //     text: { text: 'ellipse', fill: 'white' },
  //   },
  // })

  // stencil.load([r, c, c2, r2.clone()], 'basic')
  // stencil.load([c2.clone(), r2, r3, c3], 'other')

  return stencil
}

/**
 * 初始化图事件
 * @param {Graph} graph 图实例
 */
function initEvents(graph) {
  const container = graph.container

  graph.on("node:mouseenter", FunctionExt.debounce(() => {
    const ports = container.querySelectorAll('.x6-port-body')
    const texts = container.querySelectorAll('.x6-port-label')
    showPorts(ports, true)
    showPorts(texts, true)
  }))

  graph.on("node:mouseleave", FunctionExt.debounce(() => {
    const ports = container.querySelectorAll('.x6-port-body')
    const texts = container.querySelectorAll('.x6-port-label')
    showPorts(ports, false)
    showPorts(texts, false)
  }))
}